home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / mail / pathalia.zoo / src / mem.c < prev    next >
C/C++ Source or Header  |  1991-01-12  |  4KB  |  252 lines

  1. /* pathalias -- by steve bellovin, as told to peter honeyman */
  2. #ifndef lint
  3. static char    *sccsid = "@(#)mem.c    9.2 88/06/10";
  4. #endif
  5.  
  6. #include "def.h"
  7.  
  8. /* exports */
  9. long Ncount;
  10. extern void freelink(), wasted(), freetable();
  11. extern long allocation();
  12.  
  13. /* imports */
  14. extern char *Netchars;
  15. extern int Vflag;
  16. extern char *sbrk();
  17. extern void die();
  18. extern int strlen();
  19.  
  20. /* privates */
  21. STATIC void nomem();
  22. static link *Lcache;
  23. static unsigned int Memwaste;
  24.  
  25. link    *
  26. newlink()
  27. {    register link *rval;
  28.  
  29.     if (Lcache) {
  30.          rval = Lcache;
  31.         Lcache = Lcache->l_next;
  32.         strclear((char *) rval, sizeof(link));
  33.     } else if ((rval = (link * ) calloc(1, sizeof(link))) == 0)
  34.         nomem();
  35.     return rval;
  36. }
  37.  
  38. /* caution: this destroys the contents of l_next */
  39. void
  40. freelink(l)
  41.     link *l;
  42. {
  43.     l->l_next = Lcache;
  44.     Lcache = l;
  45. }
  46.  
  47. node    *
  48. newnode()
  49. {    register node *rval;
  50.  
  51.     if ((rval = (node * ) calloc(1, sizeof(node))) == 0)
  52.         nomem();
  53.     Ncount++;
  54.     return rval;
  55. }
  56.  
  57. char    *
  58. strsave(s)
  59.     char *s;
  60. {    register char *r;
  61.  
  62.     if ((r = malloc((unsigned) strlen(s) + 1)) == 0)
  63.         nomem();
  64.     (void) strcpy(r, s);
  65.     return r;
  66. }
  67.  
  68. #ifndef strclear
  69. void
  70. strclear(str, len)
  71.     register char *str;
  72.     register long len;
  73. {
  74.     while (--len >= 0)
  75.         *str++ = 0;
  76. }
  77. #endif /*strclear*/
  78.  
  79. node    **
  80. newtable(size)
  81.     long size;
  82. {    register node **rval;
  83.  
  84.     if ((rval = (node **) calloc(1, (unsigned int) size * sizeof(node *))) == 0) 
  85.         nomem();
  86.     return rval;
  87. }
  88.  
  89. void
  90. freetable(t, size)
  91.     node **t;
  92.     long size;
  93. {
  94. #ifdef MYMALLOC
  95.     extern void addtoheap();
  96.  
  97.     addtoheap((char *) t, size * sizeof(node *));
  98. #else
  99.     free((char *) t);
  100. #endif
  101. }
  102.  
  103. STATIC void
  104. nomem()
  105. {
  106.     static char epitaph[128];
  107.  
  108.     sprintf(epitaph, "out of memory (%ldk allocated)", allocation());
  109.     die(epitaph);
  110. }
  111.  
  112. /* data space allocation -- main sets `dataspace' very early */
  113. long
  114. allocation()
  115. {
  116.     static char *dataspace;
  117.     long rval;
  118.  
  119.     if (dataspace == 0) {        /* first time */
  120.         dataspace = sbrk(0);    /* &end? */
  121.         return 0;
  122.     }
  123.     rval = (sbrk(0) - dataspace)/1024;
  124.     if (rval < 0)            /* funny architecture? */
  125.         rval = -rval;
  126.     return rval;
  127. }
  128.  
  129. /* how much memory has been wasted? */
  130. void
  131. wasted()
  132. {
  133.     if (Memwaste == 0)
  134.         return;
  135.     vprintf(stderr, "memory allocator wasted %ld bytes\n", Memwaste);
  136. }
  137.  
  138. #ifdef MYMALLOC
  139.  
  140. /* use c library malloc/calloc here, and here only */
  141. #undef malloc
  142. #undef calloc
  143.  
  144. /* imports */
  145. extern char *malloc(), *calloc();
  146.  
  147. /* private */
  148. STATIC int align();
  149.  
  150. /* allocate in MBUFSIZ chunks.  4k works ok (less 16 for malloc quirks). */
  151. #define MBUFSIZ (4 * 1024 - 16)
  152.  
  153. /* 
  154.  * mess with ALIGN at your peril.  longword (== 0 mod 4)
  155.  * alignment seems to work everywhere.
  156.  */
  157.  
  158. #define ALIGN 2
  159.  
  160. typedef struct heap heap;
  161. struct heap {
  162.     heap *h_next;
  163.     long h_size;
  164. };
  165.  
  166. static heap *Mheap;    /* not to be confused with a priority queue */
  167.  
  168. STATIC void
  169. addtoheap(p, size)
  170.     char *p;
  171.     long size;
  172. {    int adjustment;
  173.     heap *pheap;
  174.  
  175.     /* p is aligned, but it doesn't hurt to check */
  176.     adjustment = align(p);
  177.     p += adjustment;
  178.     size -= adjustment;
  179.  
  180.     if (size < 1024)
  181.         return;        /* can't happen */
  182.     pheap = (heap *) p;    /* pheap is shorthand */
  183.     pheap->h_next = Mheap;
  184.     pheap->h_size = size;
  185.     Mheap = pheap;
  186. }
  187.  
  188. /*
  189.  * buffered malloc()
  190.  *    returns space initialized to 0.  calloc isn't used, since
  191.  *    strclear can be faster.
  192.  *
  193.  * free is ignored, except for very large objects,
  194.  * which are returned to the heap with addtoheap(). 
  195.  */
  196.  
  197. char    *
  198. mymalloc(n)
  199.     register unsigned int n;
  200. {    static unsigned int size; /* how much do we have on hand? */
  201.     static char *mstash;      /* where is it? */
  202.     register char *rval;
  203.  
  204.     if (n >= 1024) {        /* for hash table */
  205.         rval = malloc(n);    /* aligned */
  206.         if (rval)
  207.             strclear(rval, n);
  208.         return rval;
  209.     }
  210.  
  211.     n += align((char *) n);    /* keep everything aligned */
  212.  
  213.     if (n > size) {
  214.         Memwaste += size;    /* toss the fragment */
  215.         /* look in the heap */
  216.         if (Mheap) {
  217.             mstash = (char *) Mheap;    /* aligned */
  218.             size = Mheap->h_size;
  219.             Mheap = Mheap->h_next;
  220.         } else {
  221.             mstash = malloc(MBUFSIZ);    /* aligned */
  222.             if (mstash == 0) {
  223.                 size = 0;
  224.                 return 0;
  225.             }
  226.             size = MBUFSIZ;
  227.         }
  228.         strclear(mstash, size);        /* what if size > 2^16? */
  229.     }
  230.     rval = mstash;
  231.     mstash += n;
  232.     size -= n;
  233.     return rval;
  234. }
  235.  
  236. /*
  237.  * what's the (mis-)alignment of n?  return the complement of
  238.  * n mod 2^ALIGN
  239.  */
  240. STATIC int
  241. align(n)
  242.     char *n;
  243. {    register int abits;    /* misalignment bits in n */
  244.  
  245.     abits = (int) n & ~(0xff << ALIGN) & 0xff;
  246.     if (abits == 0)
  247.         return 0;
  248.     return (1 << ALIGN) - abits;
  249. }
  250.  
  251. #endif /*MYMALLOC*/
  252.